#define _CRT_SECURE_NO_WARNINGS 1
//#include <iostream>
//using namespace std;
//
//class Date {
//public:
//    Date(int year = 1, int month = 1, int day = 1)
//        : _year(year)
//        , _month(month)
//        , _day(day)
//    {}
//    //计算天数
//    int Days(const int year, const int month) {
//        int DateArr[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
//        if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))) {
//            return 29;
//        }
//        return DateArr[month];
//    }
//    //判断闰年
//    bool IsLeapYear(const int year) {
//        if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
//            return true;
//        return false;
//    }
//    int operator-(Date& d) {
//        //计算*this到1月1日的天数是多久
//        int ThisSum = this->_day - 1;
//        while (this->_month--) {
//            ThisSum += Days(this->_year, this->_month);
//        }
//        //计算d到1月1日的天数是多少
//        int DSum = d._day - 1;
//        while ((d._month)--) {
//            DSum += Days(d._year, d._month);
//        }
//        //假设this中的年大,d中的年小
//        Date MaxYear = *this;
//        Date MinYear = d;
//        int flag = 1;
//        if (this->_year < d._year) {
//            MaxYear = d;
//            MinYear = *this;
//            flag = -1;
//        }
//        //计算两个类之间差了多少年
//        int years = (MaxYear._year - MinYear._year) * flag;
//        int LeapYear = 0;
//        //计算*this的年和d的年之间有几个闰年
//        while (this->_year != d._year)
//        {
//
//            if (IsLeapYear(this->_year))
//            {
//                LeapYear++;
//            }
//            if (flag == 1)
//                this->_year--;
//            else
//                d._year--;
//        }
//        return (years * 365) + LeapYear + (ThisSum - DSum) - 1;
//    }
//private:
//    int _year;
//    int _month;
//    int _day;
//};
//
//int main() {
//    // int a, b;
//    // scanf("%d",&a);
//    // scanf("%d",&b);
//
//    int Ayear = 0, Amonth = 0, Aday = 0;
//    int Byear = 0, Bmonth = 0, Bday = 0;
//    scanf("%4d%2d%2d", &Ayear, &Amonth, &Aday);
//    scanf("%4d%2d%2d", &Byear, &Bmonth, &Bday);
//    Date a(Ayear, Amonth, Aday);
//    Date b(Byear, Bmonth, Bday);
//    int sum = a - b;
//    if (sum < 0)
//    {
//        sum = -sum;
//    }
//    cout << sum << endl;
//}
//// 64 位输出请用 printf("%lld")

//#include <iostream>
//using namespace std;
//int main() {
//
//    int monthday[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
//    int year1, month1, day1, year2, month2, day2;
//    scanf("%4d%2d%2d", &year1, &month1, &day1);
//    scanf("%4d%2d%2d", &year2, &month2, &day2);
//    int sum1 = 0, sum2 = 0;
//    for (int i = 1; i < year1; i++)
//    {
//        if ((i % 4 == 0 && i % 100 != 0) || i % 400 == 0)
//        {
//            sum1 += 1;
//        }
//        sum1 += 365;
//    }
//    for (int i = 1; i < year2; i++)
//    {
//        if ((i % 4 == 0 && i % 100 != 0) || i % 400 == 0)
//        {
//            sum2 += 1;
//        }
//        sum2 += 365;
//    }
//    for (int i = 1; i < month1; i++)
//    {
//        sum1 += monthday[i];
//
//        if (((year1 % 4 == 0 && year1 % 100 != 0) || year1 % 400 == 0) && i == 2)
//        {
//            sum1 += 1;
//        }
//    }
//    for (int i = 1; i < month2; i++)
//    {
//        sum2 += monthday[i];
//        if (((year2 % 4 == 0 && year2 % 100 != 0) || year2 % 400 == 0) && i == 2)
//        {
//            sum2 += 1;
//        }
//    }
//    sum1 += day1;
//    sum2 += day2;
//    cout << abs(sum1 - sum2) + 1 << endl;
//
//}

//#include <stdlib.h>
//int globalvar = 1;
//static int staticGlobalvar = 1;
//void Test()
//{
//	static int staticvar = 1;
//	int localvar = 1;
//
//	int num1[10] = { 1,2,3,4 };
//	char char2[] = "abcd";
//	const char* pchar3 = "abcd";
//	int* ptr1 = (int*)malloc(sizeof(int) * 4);
//	int* ptr2 = (int*)calloc(4, sizeof(int));
//	int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4);
//	free(ptr1);
//	free(ptr3);
//}

/*
globalvar在:数据段(静态区)
staticGlobalvar在:数据段(静态区)
staticvar在:数据段(静态区) - Test函数结束以后staticvar变量不销毁
localvar在:栈
num1在:栈

char2在:栈 - char2和num1一样都是数组,数组名表示首元素的地址,
存的是地址,在栈上

*char2在:栈 - char2在进行运算的时候代表整个数组,整个栈上的数组


pchar3在:栈 - 局部的指针,也是在栈上。
*pchar3在:代码段(常量区) - pchar3指向的是首元素的地址,
解引用得到首元素,而这个'a'就放在代码段(常量区)

ptr1在:栈 - 局部的指针,在栈上
*ptr1在:堆 - 解引用指向动态开辟的空间,在堆上
*/

//int main()
//{
//	//动态申请一个int类型的空间
//	int* ptr4 = new int;
//	//动态申请一个int类型的空间并初始化为10
//	int* ptr5 = new int(10);
//
//	//动态申请10个int类型的空间
//	int* ptr6 = new int[3];
//	//动态申请10个int类型的空间并初始化 - 跟数组的初始化是一样的
//	int* ptr7 = new int[3]{ 1,2,3 };
//	int* ptr8 = new int[5]{ 1,2,3 };
//
//	//释放
//	delete ptr4;
//	delete ptr5;
//	delete[] ptr6;
//	delete[] ptr7;
//	delete[] ptr8;
//
//	return 0;
//}

//void Test()
//{
//	//管理对象
//	int* ptr4 = new int;
//	int* ptr5 = new int(3);
//	delete ptr4;
//	delete ptr5;
//	//管理对象数组
//	int* ptr6 = new int[3];
//	delete[] ptr6;
//}

//#include <iostream>
//using namespace std;
//class A
//{
//public:
//	A(int a = 1)
//		:_a(a)
//	{
//		cout << "A():" << this << endl;
//	}
//	~A()
//	{
//		cout << "~A():" << this << endl;
//	}
//private:
//	int _a;
//};
//

//int main()
//{
//	//new/delete 和 malloc/free最大区别是 new/deeletc对于
//	//自定义类型除了开空间还会调用构造函数和析构函数。
//	A* p1 = (A*)malloc(sizeof(A));
//	A* p2 = new A;//没有默认构造就会报错,当然也可以自己传参
//	//A* p3 = new A(1);//这里有点像匿名对象,但不是匿名对象
//	//这是在堆上new一个对象,然后构造。然后把对象的地址返回给p3
//
//	free(p1);//释放空间
//	delete p2;//析构+释放空间 - 释放空间之前先调析构函数
//
//	//创建多个对象
//	A* p4 = (A*)malloc(sizeof(A) * 10);
//	A* p5 = new A[10];//new了10个A对象,那么就会调用10次构造函数
//	free(p4);
//	delete[] p5;//析构的时候会对这10个对象依次析构,然后释放内存空间
//
//	//创建多个对象并且初始化
//	//A aa1(1);
//	//A aa2(2);
//	//A* p6 = new A[10]{aa1,aa2};//调用有名对象,后面的调默认构
//	//造,没默认构造就报错
//
//	//也可以直接用匿名对象
//	//A* p6 = new A[10]{ A(1),A(2) };
//	//也可以用隐式类型转换
//	A* p6 = new A[10]{ 1,2 };//本质是构造临时对象,然后走拷贝构造,
//	//编译器优化成了直接构造也是一样的
//	delete[] p6;
//
//	return 0;
//}

//struct ListNode
//{
//	int _index;
//	ListNode* _next;
//	ListNode(int index = 1)
//		:_index(index)
//		,_next(nullptr)
//	{}
//};
//int main()
//{
//	//new相当于开空间+调用ListNode的构造函数初始化
//	ListNode* n1 = new ListNode(1);
//	ListNode* n2 = new ListNode(2);
//	ListNode* n3 = new ListNode(3);
//	ListNode* n4 = new ListNode(4);
//	n1->_next = n2;
//	n2->_next = n3;
//	n3->_next = n4;
//	//释放
//	delete n1;
//	delete n2;
//	delete n3;
//	delete n4;
//	return 0;
//}

///*
//operator new:该函数实际通过malloc来申请空间，
//当malloc申请空间成功时直接返回,申请空间失败，
//尝试执行空间不足应对措施，如果该应对措施用户设置了，
//则继续申请，否则抛异常。
//operator new本质是对malloc的一个封装
//封装是因为malloc失败会返回0,而operaotr new失败之后会抛异常
//异常是C++处理错误的一种方式
//*/
//void* __CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
//{
//	// try to allocate size bytes
//	void* p;
//	while ((p = malloc(size)) == 0)
//		if (_callnewh(size) == 0)
//		{
//			// report no memory
//			// 如果申请内存失败了，这里会抛出bad_alloc 类型异常
//			static const std::bad_alloc nomem;
//			_RAISE(nomem);
//		}
//	return (p);
//}
///*
//operator delete:该函数最终是通过free来释放空间的
//operator delete封装的不是free,而是封装的一个_free_dbg
//的一个函数,其实_free_dbg就是free,其实库里面的free是一个
//宏函数,所以我们也可以理解为operator delete就是对free的封装。
//*/
//void operator delete(void* pUserData)
//{
//	_CrtMemBlockHeader* pHead;
//	RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));
//	if (pUserData == NULL)
//		return;
//	_mlock(_HEAP_LOCK);  /* block other threads */
//	__TRY
//		/* get a pointer to memory block header */
//		pHead = pHdr(pUserData);
//	/* verify block type */
//	_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
//	_free_dbg(pUserData, pHead->nBlockUse);
//	__FINALLY
//		_munlock(_HEAP_LOCK);  /* release other threads */
//	__END_TRY_FINALLY
//		return;
//}
///*
//free的实现 - 底层也是调_free_dbg
//*/
//#define   free(p)	_free_dbg(p, _NORMAL_BLOCK)

//#include <iostream>
//using namespace std;
//class A
//{
//public:
//	A(int a = 1)
//		:_a(a)
//	{
//		cout << "A():" << this << endl;
//	}
//	~A()
//	{
//		cout << "~A():" << this << endl;
//	}
//private:
//	int _a;
//};
//
//int main()
//{
//	//申请空间+构造函数
//	A* p2 = new A(1);
//	A* p3 = new A;
//	//析构函数+释放空间
//	delete p2;
//	delete p3;
//	return 0;
//}
//#include <iostream>
//using namespace std;
//void Func()
//{
//	int* p1 = new int[1024 * 1024 * 100];//400MB
//	cout << p1 << endl;
//	int* p2 = new int[1024 * 1024 * 100];
//	cout << p2 << endl;
//	int* p3 = new int[1024 * 1024 * 100];
//	cout << p3 << endl;
//	int* p4 = new int[1024 * 1024 * 100];
//	cout << p4 << endl;
//	int* p5 = new int[1024 * 1024 * 100];
//	cout << p5 << endl;
//	
//	//当申请p5的时候就会失败,因为没那么大内存了
//	//弹出的框就是抛异常了。
//	while (1)
//	{
//		int* p5 = new int[1024 * 1024 * 100];
//		cout << p5 << endl;
//	}
//}
//int main()
//{
//	try
//	{
//		Func();
//	}
//	catch (const exception& e)
//	{
//		cout << e.what() << endl;
//	}
//	return 0;
//}
//class A
//{ };
////operator new我们是可以直接使用的
//int main()
//{
//	//跟malloc区别是失败会抛异常,所以不用检查返回值
//	//但是没有调用构造函数
//	//new也一样,不用检查返回值
//	A* p1 = (A*)operator new(sizeof(A));
//	return 0;
//}

//#include <iostream>
//using namespace std;
//class A
//{
//public:
//	A(int a = 1)
//		:_a(a)
//	{
//		cout << "A():" << this << endl;
//	}
//	~A()
//	{
//		cout << "~A():" << this << endl;
//	}
//private:
//	int _a;
//};
//int main()
//{
//	//构造函数是没办法显示调用的
//	//也就是说new没办法拆分为operator new和调拷贝构造
//	A* ptr1 = (A*)operator new(sizeof(A));
//	//ptr1->A(1);//err
//
//	//相对这块显示调用构造函数的空间的用法叫做定位new
//	new(ptr1)A(101);//这个时候就会对p1指向的空间调用构造函数初始化
//
//	//析构函数支持显示调用
//	ptr1->~A();
//	operator delete(ptr1);
//	//上半部分就充当了new的功能,下半部分就充当
//	//了detete的功能,和new和delete达到的效果一摸一样
//	return 0;
//}
/*
但是平时不会这样写,这个定位new和显示调用析构
有些地方为了提高效率申请内存的时候如果直接用new
的话底层就是调operator new,也就是说调malloc了,
这种方式效率比较低,那么就会写一个叫内存池的东西
那如果我的空间是从我的内存池出来的,那就开好了空间
初始化的话就要用定位new去初始化,析构就是显示调用
析构,然后释放内存池,
*/

//#include<iostream>
//using namespace std;
//class ClassA
//{
//public:
//	ClassA()
//	{
//		cout << "ClassA()" << endl;
//	}
//	~ClassA()
//	{
//		cout << "~ClassA()" << endl;
//	}
//};
//int main()
//{
//	ClassA* pclassa = new ClassA[5];
//	delete[] pclassa;
//	char* p = new char[100];
//	delete[] p;
//	return 0;
//}
#include <iostream>
using namespace std;
int globalVar = 1;
static int staticGlobalVar = 1;
void Test()
{
	static int staticVar = 1;
	int localVar = 1;
	int num1[10] = { 1, 2, 3, 4 };
	char char2[] = "abcd";
	const char* pChar3 = "abcd";
	int* ptr1 = (int*)malloc(sizeof(int) * 4);
	int* ptr2 = (int*)calloc(4, sizeof(int));
	int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4);
	cout << sizeof(num1) << " " << sizeof(char2) << " " << strlen(char2) << endl;
	cout << sizeof(pChar3) << " " << strlen(pChar3) << " " << sizeof(ptr1) << endl;
	free(ptr1);
	free(ptr3);
}
int main()
{
	Test();
	return 0;
}
